# Copyright (c) 2019 Presto Labs Pte. Ltd.
# Author: jaewon

import datetime
import os

from coin.base.datetime_util import to_datetime
from coin.exchange.base.tick import FixedTickPrice
from coin.strategy.marketsim.core import spec_pb2
from experimental.prophet.craps.universe import universe_btc

from coin.strategy.marketsim import result_util
from coin.strategy.marketsim.strategy.pass_unhedge_model import PassUnhedgeModelSimStrategy

run_id = None
sim_out_dir = None


def prepare(args, ref_ts, **kwargs):
  global run_id, sim_out_dir
  run_id = kwargs.get('run_id', None)
  sim_out_dir = kwargs.get('sim_out_dir', None)


def get_machine():
  return 'feed-01.ap-northeast-1.aws'


def get_time_ranges():
  ranges = []
  cur_dt = datetime.datetime(2019, 7, 20, 0, 0, 0)
  end_dt = datetime.datetime(2019, 8, 13, 0, 0, 0)
  while cur_dt < end_dt:
    if cur_dt.weekday() != 4:
      ranges.append((cur_dt, cur_dt + datetime.timedelta(hours=24)))
    cur_dt += datetime.timedelta(hours=24)
  return ranges


def get_strategy(from_ts, to_ts):
  sim_spec = spec_pb2.MarketSimSpecProto(
      latency=1 * 10**9,  # 1 sec,
      feed_cut_time_allowance=300 * 10**9,  # 5 min
      clear_on_feed_cut=True)

  machine = get_machine()

  symbol_infos = universe_btc(from_ts)
  symbol_info = symbol_infos[0]  # fxbtcjpy
  product_sim_spec = spec_pb2.ProductSpecProto(symbol=str(symbol_info.product),
                                               settlement_currency='JPY',
                                               inverse=False,
                                               maker_fee=0.,
                                               taker_fee=0.,
                                               support_post_only=False,
                                               money_multiplier=1.,
                                               fastfeed_machine=machine,
                                               fastfeed_sub_req=symbol_info.sub_req)

  tick_price = symbol_info.product_info.gen_tick_price()
  assert isinstance(tick_price, FixedTickPrice)

  strategy_list = []
  for offset in (5., 6., 7.):  # 0., 3., 5., 7.):
    for stack in (5, 10):
      lot_size = 5. / stack

      name = 'pu_model.fxbtcjpy.offset%.0fbp.%02dstack.%s' % (
          offset, stack, to_datetime(from_ts).strftime('%Y%m%d'))

      sampler_offsets = {
          'sampler/low_vol': offset,
          'sampler/mid_vol': offset,
          'sampler/high_vol': offset,
      }

      params = {
          'pass_product_sim_spec': product_sim_spec,
          'pass_symbol_info': symbol_info,
          'pass_product_tick': tick_price.tick_size,
          'ref_symbol_nicks': [],
          'model_filepath': 'model3.pkl.gz',
          'machine': machine,
          'date': from_ts,
          'sampler_offsets': sampler_offsets,
          'lot_size': lot_size,
          'min_pos': -lot_size * stack,
          'max_pos': lot_size * stack,
          'min_fire_period': 8 * (10**9),
          'post_only': False,
          'sim_spec': sim_spec,
          'name': name,
      }
      strategy = PassUnhedgeModelSimStrategy(**params)
      strategy_list.append(strategy)

  return strategy_list


def get_strategy_result(strategy):
  if run_id is not None and sim_out_dir is not None:
    out_dir = os.path.join(sim_out_dir, 'run-' + run_id)
    os.makedirs(out_dir, exist_ok=True)
    out_path = os.path.join(out_dir, strategy.name + '.gz')
    strategy.sim.dump_sim_result(out_path, tag=strategy.name)

  sim_stat = strategy.get_sim_stat()
  sim_stat.tag = strategy.name
  return sim_stat


def aggregate_result(results):
  result_util.aggregate_sim_stat(results, show_stat_only=False)
  # for res in results:
  #  print(res)
  # return result_util.aggregate_sim_result(results)
